<!--
# coding=UTF-8
# Copyright (c) 2025 Bird Software Solutions Ltd
# This program and the accompanying materials
# are made available under the terms of the Eclipse Public License 2.0
# which accompanies this distribution, and is available at
# https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
# Contributors:
#    Neil Mackenzie - initial API and implementation
#    Benjamin Arfa - improvements
#
-->
{% extends 'base.html' %}
{% load static %}

{% block title %}Member Hierarchy Editor{% endblock %}

{% block content %}
<style>
    .hierarchy-page {
        margin: 0;
        padding: 0;
        height: calc(100vh - 120px);
        width: 100%;
        overflow: hidden;
    }

    .hierarchy-header {
        background-color: #2c3e50;
        color: white;
        padding: 15px 20px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        box-shadow: 0 2px 5px rgba(0,0,0,0.1);
    }

    .hierarchy-title h2 {
        margin: 0;
        font-size: 24px;
    }

    .hierarchy-subtitle {
        font-size: 14px;
        color: #bdc3c7;
        margin-top: 2px;
    }

    .toolbar {
        display: flex;
        gap: 10px;
        align-items: center;
    }

    .tool-btn {
        background-color: #34495e;
        color: white;
        border: none;
        padding: 10px 15px;
        border-radius: 4px;
        cursor: pointer;
        transition: background-color 0.3s;
        font-size: 13px;
        white-space: nowrap;
    }

    .tool-btn:hover {
        background-color: #4a6741;
    }

    .tool-btn.active {
        background-color: #27ae60;
    }

    .export-btn {
        background-color: #3498db;
    }

    .export-btn:hover {
        background-color: #2980b9;
    }

    .import-btn {
        background-color: #e67e22;
    }

    .import-btn:hover {
        background-color: #d35400;
    }

    .clear-btn {
        background-color: #e74c3c;
    }

    .clear-btn:hover {
        background-color: #c0392b;
    }

    .zoom-indicator {
        background-color: #7f8c8d;
        color: white;
        padding: 8px 12px;
        border-radius: 4px;
        font-size: 13px;
        cursor: pointer;
        user-select: none;
        transition: background-color 0.3s;
        border: none;
        min-width: 60px;
        text-align: center;
    }

    .zoom-indicator:hover {
        background-color: #95a5a6;
    }

    .hierarchy-content {
        display: flex;
        height: calc(100vh - 180px);
        width: 10000px;
        height: 10000px;
        position: relative;
    }

    .sidebar {
        width: 320px;
        background: white;
        border-right: 1px solid #ddd;
        padding: 20px;
        overflow-y: auto;
        box-shadow: 2px 0 5px rgba(0,0,0,0.1);
    }

    .sidebar-header {
        margin-bottom: 20px;
        padding-bottom: 15px;
        border-bottom: 2px solid #eee;
    }

    .sidebar-header h3 {
        color: #2c3e50;
        font-size: 20px;
        margin: 0 0 10px 0;
    }

    .hierarchy-selector {
        margin-bottom: 20px;
    }

    .hierarchy-selector label {
        display: block;
        margin-bottom: 5px;
        font-weight: bold;
        color: #34495e;
    }

    .hierarchy-selector select {
        width: 100%;
        padding: 10px 12px;
        border: 2px solid #ddd;
        border-radius: 4px;
        font-size: 14px;
        background: white;
        color: #2c3e50;
    }

    .hierarchy-selector select:focus {
        outline: none;
        border-color: #3498db;
    }

    .search-container {
        margin-bottom: 15px;
    }

    .search-container label {
        display: block;
        margin-bottom: 5px;
        font-weight: bold;
        color: #34495e;
    }

    .search-input {
        width: auto;
        padding: 10px 12px;
        border: 2px solid #ddd;
        border-radius: 4px;
        font-size: 14px;
    }

    .search-input:focus {
        outline: none;
        border-color: #3498db;
    }

    .sidebar-content {
        max-height: calc(100vh - 400px);
        overflow-y: auto;
    }

    .workspace {
        flex: 1;
        position: relative;
        overflow: hidden;
        background: #ecf0f1;
        background-image:
            radial-gradient(circle, #bdc3c7 1px, transparent 1px);
        background-size: 20px 20px;
        min-height: 600px;
        min-width: 800px;
    }

    .workspace.drag-over {
        background-color: rgba(52, 152, 219, 0.1);
        border: 3px dashed #3498db;
    }

    #canvas {
        position: absolute;
        top: 0;
        left: 0;
        border: none;
        background: transparent;
        cursor: default;
        pointer-events: auto;
        z-index: 5;
        display: block;
    }

    #canvas.delete-arrow-mode {
        pointer-events: auto;
        cursor: crosshair;
    }



    .concept-box {
        position: absolute;
        background: white;
        border: 3px solid #3498db;
        border-radius: 8px;
        padding: 15px;
        min-width: 200px;
        max-width: 350px;
        box-shadow: 0 4px 12px rgba(0,0,0,0.15);
        cursor: move;
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        z-index: 10;
    }

    .concept-box:hover {
        border-color: #2980b9;
        box-shadow: 0 6px 20px rgba(0,0,0,0.2);
        transform: translateY(-2px);
    }

    .concept-box.selected {
        border-color: #27ae60;
        box-shadow: 0 0 0 3px rgba(39, 174, 96, 0.3);
    }

    .concept-box.connecting {
        border-color: #f39c12;
        box-shadow: 0 0 0 3px rgba(243, 156, 18, 0.3);
    }

    .concept-box.deleting {
        border-color: #e74c3c;
        box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.3);
    }

    .concept-box.dragging {
        opacity: 0.8;
        transform: rotate(2deg) scale(1.02);
        z-index: 1000;
    }

    .drag-handle {
        position: absolute;
        top: 8px;
        right: 8px;
        width: 24px;
        height: 24px;
        background: #95a5a6;
        border-radius: 4px;
        cursor: grab;
        display: flex;
        align-items: center;
        justify-content: center;
        opacity: 0.7;
        transition: opacity 0.3s;
    }

    .drag-handle:hover {
        opacity: 1;
        background: #7f8c8d;
    }

    .drag-handle:active {
        cursor: grabbing;
    }

    .drag-icon {
        width: 12px;
        height: 12px;
        background: white;
        border-radius: 2px;
        position: relative;
    }

    .drag-icon::before,
    .drag-icon::after {
        content: '';
        position: absolute;
        width: 3px;
        height: 3px;
        background: #95a5a6;
        border-radius: 50%;
        top: 2px;
        left: 2px;
        box-shadow: 6px 0 0 #95a5a6, 0 6px 0 #95a5a6, 6px 6px 0 #95a5a6;
    }

    .delete-btn {
        position: absolute;
        top: 8px;
        left: 8px;
        width: 24px;
        height: 24px;
        background: #e74c3c;
        color: white;
        border: none;
        border-radius: 50%;
        cursor: pointer;
        font-size: 14px;
        font-weight: bold;
        display: flex;
        align-items: center;
        justify-content: center;
        line-height: 1;
        transition: background-color 0.3s;
    }

    .delete-btn:hover {
        background: #c0392b;
    }

    .box-content {
        margin-top: 10px;
        pointer-events: none;
    }

    .box-content .field-group {
        margin-bottom: 6px;
        padding-right: 20px;
        overflow-wrap: anywhere;
    }

    .box-header {
        font-weight: bold;
        margin-bottom: 8px;
        color: #2c3e50;
        font-size: 16px;
    }

    .field-label {
        display: block;
        font-size: 11px;
        color: #7f8c8d;
        margin-bottom: 3px;
        text-transform: uppercase;
        font-weight: 600;
        letter-spacing: 0.5px;
    }

    .field-input {
        width: 100%;
        padding: 6px 8px;
        border: 2px solid #bdc3c7;
        border-radius: 4px;
        font-size: 13px;
        background: white;
        overflow-wrap: anywhere;
        color: #2c3e50;
        pointer-events: auto;
        transition: border-color 0.3s;
    }

    .field-input:focus {
        outline: none;
        border-color: #3498db;
        box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);
    }

    .id-display {
        background: #f8f9fa;
        color: #6c757d;
        padding: 6px 8px;
        border: 2px solid #dee2e6;
        border-radius: 4px;
        font-size: 12px;
        font-family: 'Courier New', monospace;
        overflow-wrap: anywhere;
        cursor: not-allowed;
        font-weight: bold;
    }

    .name-input {
        font-weight: bold;
        font-size: 14px;
        overflow-wrap: anywhere;
    }

    .text-input {
        resize: vertical;
        min-height: 50px;
        font-family: inherit;
        overflow-wrap: anywhere;
    }

    .member-item {
        background: #f8f9fa;
        border: 2px solid #dee2e6;
        border-radius: 6px;
        padding: 12px;
        margin-bottom: 10px;
        cursor: grab;
        transition: all 0.3s;
        user-select: none;
        overflow-wrap: anywhere;
    }

    .member-item:hover {
        background: #e9ecef;
        border-color: #3498db;
        transform: translateX(3px);
    }

    .member-item:active {
        cursor: grabbing;
    }

    .member-item.dragging {
        opacity: 0.5;
        transform: rotate(3deg);
    }

    .member-item.used {
        background: #fff3cd;
        border-color: #ffeaa7;
        opacity: 0.7;
        cursor: not-allowed;
    }

    .member-name {
        font-weight: bold;
        color: #2c3e50;
        font-size: 14px;
        display: block;
        margin-bottom: 3px;
    }

    .member-id {
        font-size: 12px;
        color: #7f8c8d;
        font-family: 'Courier New', monospace;
    }

    .member-status {
        font-size: 11px;
        color: #e74c3c;
        font-style: italic;
        margin-top: 3px;
    }

    .no-hierarchy-message {
        text-align: center;
        color: #7f8c8d;
        font-style: italic;
        padding: 40px 20px;
        border: 2px dashed #bdc3c7;
        border-radius: 8px;
        margin: 20px 0;
        background: #f8f9fa;
    }

    .loading {
        text-align: center;
        padding: 40px 20px;
        color: #7f8c8d;
        font-style: italic;
    }

    .error-message {
        background: #e74c3c;
        color: white;
        padding: 15px;
        border-radius: 6px;
        margin: 15px 0;
        font-weight: bold;
    }

    .tool-status {
        position: fixed;
        top: 140px;
        left: 20px;
        background: rgba(52, 73, 94, 0.95);
        color: white;
        padding: 12px 18px;
        border-radius: 6px;
        font-size: 14px;
        z-index: 1000;
        max-width: 300px;
        box-shadow: 0 4px 12px rgba(0,0,0,0.3);
        transition: opacity 0.3s;
    }

    .tool-status:empty {
        display: none;
    }

    .instructions {
        position: fixed;
        bottom: 20px;
        right: 20px;
        background: rgba(52, 73, 94, 0.95);
        color: white;
        padding: 20px;
        border-radius: 8px;
        max-width: 350px;
        font-size: 13px;
        z-index: 1000;
        box-shadow: 0 4px 12px rgba(0,0,0,0.3);
        line-height: 1.5;
    }

    .instructions h3 {
        margin: 0 0 15px 0;
        color: #ecf0f1;
        font-size: 16px;
    }

    .instructions p {
        margin: 8px 0;
    }

    .instructions strong {
        color: #3498db;
    }

    /* Responsive adjustments */
    @media (max-width: 768px) {
        .sidebar {
            width: 280px;
        }

        .tool-btn {
            padding: 8px 10px;
            font-size: 11px;
        }

        .hierarchy-header {
            flex-direction: column;
            gap: 10px;
            align-items: stretch;
        }

        .toolbar {
            justify-content: center;
            flex-wrap: wrap;
        }
    }
</style>

<div class="hierarchy-page">
    <div class="hierarchy-header">
        <div class="hierarchy-title">
            <h2 style="color: white;">Member Hierarchy Editor</h2>
            {% if selected_hierarchy %}
                <div class="hierarchy-subtitle">{{ selected_hierarchy.name }}</div>
            {% endif %}
            <a href="{% url 'pybirdai:workflow_task' task_number=1 operation='review' %}">Back to Review</a>

        </div>
        <div class="toolbar">
            <button id="arrowTool" class="tool-btn" onclick="toggleTool('arrow')" title="Connect nodes (A)">
                ➜ Create Arrow
            </button>
            <button id="deleteArrowTool" class="tool-btn" onclick="toggleTool('deleteArrow')" title="Delete arrows (D)">
                ✂ Delete Arrow
            </button>
            <button id="exportBtn" class="tool-btn export-btn" onclick="exportHierarchy()" title="Export hierarchy (E)">
                📤 Export
            </button>
            <button id="saveBtn" class="tool-btn export-btn" onclick="saveHierarchy()" title="Export hierarchy (E)">
                📤 Save to Database
            </button>
            <!-- <button id="importBtn" class="tool-btn import-btn" onclick="document.getElementById('fileInput').click()" title="Import hierarchy (I)">
                📥 Import
            </button> -->
            <button id="clearBtn" class="tool-btn clear-btn" onclick="clearAll()" title="Clear all (C)">
                🗑 Clear
            </button>
            <button id="zoomIndicator" class="zoom-indicator" onclick="resetZoom()" title="Reset zoom (R)">
                100%
            </button>
            <button id="fitBtn" class="tool-btn" onclick="fitToView()" title="Fit all nodes to view (F)">
                🔍 Fit All
            </button>
        </div>
    </div>

    <input type="file" id="fileInput" accept=".json" style="display: none" onchange="importHierarchy(event)">

    {% csrf_token %}

    <div class="hierarchy-content">
        <div class="sidebar">
            <div class="sidebar-header">
                <h3>Hierarchy Manager</h3>
            </div>

            <div class="hierarchy-selector">
                <label for="hierarchySelect">Select Hierarchy:</label>
                <select id="hierarchySelect" onchange="loadHierarchy(this.value)">
                    <option value="">Choose a hierarchy...</option>
                    {% for hierarchy in hierarchies %}
                        <option value="{{ hierarchy.member_hierarchy_id }}"
                                {% if hierarchy.member_hierarchy_id == selected_hierarchy_id %}selected{% endif %}>
                            {{ hierarchy.name }}
                        </option>
                    {% endfor %}
                </select>
            </div>

            {% if error %}
                <div class="error-message">{{ error }}</div>
            {% endif %}

            {% if selected_hierarchy %}
                <div class="search-container">
                    <label for="searchInput">Search Members:</label>
                    <input type="text" id="searchInput" class="search-input" placeholder="Type to filter members..." onkeyup="filterMembers()">
                </div>

                <div class="sidebar-content" id="sidebarContent">
                    <div class="loading">Loading members...</div>
                </div>
            {% else %}
                <div class="no-hierarchy-message" id="noHierarchyMessage">
                    Select a hierarchy from the dropdown above to start editing
                </div>
            {% endif %}
        </div>

        <div class="workspace drop-zone" id="workspace"
             ondragover="handleWorkspaceDragOver(event)"
             ondragenter="handleWorkspaceDragEnter(event)"
             ondragleave="handleWorkspaceDragLeave(event)"
             ondrop="handleWorkspaceDrop(event)">
            <canvas id="canvas"></canvas>
        </div>
    </div>
</div>

<div class="tool-status" id="toolStatus"></div>

<!--
<div class="instructions">
    <h3>How to Use</h3>
    <p><strong>Arrow Tool (A):</strong> Click and drag to connect concepts</p>
    <p><strong>Delete Arrow (D):</strong> Click on arrows to delete them</p>
    <p><strong>Drag Concepts:</strong> Use the handle to move concepts around</p>
    <p><strong>Delete Concepts:</strong> Click the red × to delete a concept</p>
    <p><strong>Zoom:</strong> Mouse wheel to zoom, click percentage to reset</p>
    <p><strong>Fit All (F):</strong> Auto-fit all nodes to view</p>
    <p><strong>Auto Layout (L):</strong> Organize all nodes in a grid</p>
    <p><strong>Navigate:</strong> Shift + Scroll (up/down), Ctrl + Scroll (left/right), or drag empty canvas</p>
    <p><strong>Connections:</strong> Red circle = source, Green square = target</p>
    <p><strong>Add Members:</strong> Drag from sidebar to canvas</p>
</div> -->

<script>
// Global variables
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const workspace = document.getElementById('workspace');
const arrowTool = document.getElementById('arrowTool');
const deleteArrowTool = document.getElementById('deleteArrowTool');
const exportBtn = document.getElementById('exportBtn');
const importBtn = document.getElementById('importBtn');
const fileInput = document.getElementById('fileInput');
const clearBtn = document.getElementById('clearBtn');
const zoomIndicator = document.getElementById('zoomIndicator');
const sidebar = document.querySelector('.sidebar');
const searchInput = document.getElementById('searchInput');
const sidebarContent = document.getElementById('sidebarContent');
const noHierarchyMessage = document.getElementById('noHierarchyMessage');

let currentTool = null;
let hierarchy_info = null;
let boxes = [];
let arrows = [];
let connectingFrom = null;
let deletingFrom = null;
let nextId = 1;
let draggedBox = null;
let dragOffset = { x: 0, y: 0 };
let availableMembers = [];
let usedMemberIds = new Set();

// Canvas drag navigation variables
let isDraggingCanvas = false;
let canvasDragStart = { x: 0, y: 0 };
let canvasLastPos = { x: 0, y: 0 };



// Zoom variables
let zoomLevel = 1.0;
const zoomMin = 0.2;
const zoomMax = 3.0;
const zoomStep = 0.1;

// Initialize the canvas
function resizeCanvas() {
    if (canvas && workspace) {
        const rect = workspace.getBoundingClientRect();
        const width = Math.max(rect.width, 800);
        const height = Math.max(rect.height, 600);

        canvas.width = width;
        canvas.height = height;
        canvas.style.width = width + 'px';
        canvas.style.height = height + 'px';

        // Ensure canvas is properly positioned and reset any transforms
        canvas.style.position = 'absolute';
        canvas.style.top = '0';
        canvas.style.left = '0';
        canvas.style.transform = 'none';
        canvas.style.transformOrigin = 'none';

        drawArrows();
    }
}

// Handle zoom functionality and navigation
function handleZoom(event) {
    // Handle navigation with Shift/Ctrl + scroll
    if (event.altKey) {
        // Shift + scroll for vertical panning
        event.preventDefault();
        const panDistance = 150;
        let delta = event.deltaY > 0 ? -panDistance : panDistance;
        panView(0, delta);
        return;
    }

    if (event.ctrlKey || event.metaKey) {
        // Ctrl/Cmd + scroll for horizontal panning
        event.preventDefault();
        const panDistance = 150;
        let delta = event.deltaY > 0 ? -panDistance : panDistance;
        panView(delta, 0);
        return;
    }

    // Regular zoom functionality
    event.preventDefault();
    const delta = event.deltaY > 0 ? -zoomStep : zoomStep;
    const newZoom = Math.max(zoomMin, Math.min(zoomMax, zoomLevel + delta));

    if (newZoom !== zoomLevel) {
        zoomLevel = newZoom;
        applyZoom();
    }
}

function applyZoom() {
    workspace.style.transform = `scale(${zoomLevel})`;
    workspace.style.transformOrigin = '0 0';
    zoomIndicator.textContent = Math.round(zoomLevel * 100) + '%';

    // Keep canvas unscaled - it will handle zoom in drawArrows
    if (canvas) {
        canvas.style.transform = 'none';
        canvas.style.transformOrigin = 'none';
    }

    // Redraw arrows with proper scaling
    drawArrows();
}

function resetZoom() {
    zoomLevel = 1.0;
    applyZoom();
    drawArrows();
}

function panView(deltaX, deltaY) {
    if (boxes.length === 0) return;

    // Move all boxes by the specified delta
    boxes.forEach(box => {
        box.x += deltaX;
        box.y += deltaY;
        const boxElement = document.getElementById(box.id);
        if (boxElement) {
            boxElement.style.left = box.x + 'px';
            boxElement.style.top = box.y + 'px';
        }
    });

    // Redraw arrows to match new positions
    setTimeout(() => {
        drawArrows();
    }, 10);
}

function startCanvasDrag(x, y) {
    isDraggingCanvas = true;
    canvasDragStart.x = x;
    canvasDragStart.y = y;
    canvasLastPos.x = x;
    canvasLastPos.y = y;
    workspace.style.cursor = 'grabbing';
}

function updateCanvasDrag(x, y) {
    if (!isDraggingCanvas || boxes.length === 0) return;

    const deltaX = x - canvasLastPos.x;
    const deltaY = y - canvasLastPos.y;

    // Apply the movement to all boxes
    panView(deltaX / zoomLevel, deltaY / zoomLevel);

    canvasLastPos.x = x;
    canvasLastPos.y = y;
}

function endCanvasDrag() {
    isDraggingCanvas = false;
    workspace.style.cursor = 'default';
}

function handleKeyboard(event) {
    // Check if user is typing in an input field
    const activeElement = document.activeElement;
    const isInputField = activeElement && (
        activeElement.tagName === 'INPUT' ||
        activeElement.tagName === 'TEXTAREA' ||
        activeElement.tagName === 'SELECT' ||
        activeElement.isContentEditable
    );
    // Don't trigger shortcuts when typing in input fields
    if (isInputField) return;
    if (event.ctrlKey || event.metaKey) return;
}

// Tool management
function toggleTool(tool) {
    if (currentTool === tool) {
        setTool(null);
    } else {
        setTool(tool);
    }
}

function setTool(tool) {
    currentTool = tool;
    connectingFrom = null;
    deletingFrom = null;

    // Update button states
    arrowTool.classList.toggle('active', tool === 'arrow');
    deleteArrowTool.classList.toggle('active', tool === 'deleteArrow');

    // Update canvas cursor
    canvas.classList.toggle('delete-arrow-mode', tool === 'deleteArrow');

    // Clear any connecting states
    boxes.forEach(box => {
        const boxElement = document.getElementById(box.id);
        if (boxElement) {
            boxElement.classList.remove('connecting', 'deleting');
        }
    });

    updateToolStatus();
}

function updateToolStatus() {
    const toolStatus = document.getElementById('toolStatus');
    if (currentTool === 'arrow') {
        if (connectingFrom) {
            toolStatus.textContent = 'Arrow Tool: Now click another concept to connect';
        } else {
            toolStatus.textContent = 'Arrow Tool: Click a concept, then click another to connect them';
        }
    } else if (currentTool === 'deleteArrow') {
        if (deletingFrom) {
            toolStatus.textContent = 'Delete Arrow Tool: Now click another concept to delete connection';
        } else {
            toolStatus.textContent = 'Delete Arrow Tool: Click on arrows to delete them, or click two connected concepts';
        }
    } else {
        toolStatus.textContent = '';
    }
}

function populateSidebar() {
    if (!hierarchy_info || !hierarchy_info.allowed_members) {
        if (sidebarContent) {
            sidebarContent.innerHTML = '<div class="loading">No members available</div>';
        }
        return;
    }

    availableMembers = Object.entries(hierarchy_info.allowed_members).map(([id, name]) => ({
        id: id,
        name: name
    }));

    filterMembers();
}

function filterMembers() {
    if (!availableMembers.length) return;

    const searchTerm = searchInput ? searchInput.value.toLowerCase() : '';
    const filteredMembers = availableMembers.filter(member =>
        member.name.toLowerCase().includes(searchTerm) ||
        member.id.toLowerCase().includes(searchTerm)
    );

    let html = '';
    filteredMembers.forEach(member => {
        const isUsed = usedMemberIds.has(member.id);
        const className = isUsed ? 'member-item used' : 'member-item';
        html += `
            <div class="${className}"
                 draggable="${!isUsed}"
                 data-member-id="${member.id}"
                 data-member-name="${member.name}"
                 ondragstart="handleMemberDragStart(event)"
                 ondragend="handleMemberDragEnd(event)">
                <span class="member-name">${member.name}</span>
                <span class="member-id">${member.id}</span>
                ${isUsed ? '<span class="member-status">Already in hierarchy</span>' : ''}
            </div>
        `;
    });

    if (html === '') {
        html = '<div class="no-hierarchy-message">No members match your search</div>';
    }

    if (sidebarContent) {
        sidebarContent.innerHTML = html;
    }
}

function handleMemberDragStart(event) {
    const item = event.target;
    if (item.classList.contains('used')) {
        event.preventDefault();
        return;
    }

    item.classList.add('dragging');
    event.dataTransfer.setData('text/plain', JSON.stringify({
        memberId: item.dataset.memberId,
        memberName: item.dataset.memberName
    }));
}

function handleMemberDragEnd(event) {
    event.target.classList.remove('dragging');
}

// Workspace drag and drop handlers
function handleWorkspaceDragOver(event) {
    event.preventDefault();
}

function handleWorkspaceDragEnter(event) {
    if (event.dataTransfer.types.includes('text/plain')) {
        workspace.classList.add('drag-over');
    }
}

function handleWorkspaceDragLeave(event) {
    if (!workspace.contains(event.relatedTarget)) {
        workspace.classList.remove('drag-over');
    }
}

function handleWorkspaceDrop(event) {
    event.preventDefault();
    workspace.classList.remove('drag-over');

    try {
        const data = JSON.parse(event.dataTransfer.getData('text/plain'));
        const rect = workspace.getBoundingClientRect();
        const x = (event.clientX - rect.left) / zoomLevel;
        const y = (event.clientY - rect.top) / zoomLevel;

        createBoxFromMember(data.memberId, data.memberName, x, y);
    } catch (e) {
        console.error('Error handling drop:', e);
    }
}

function createBoxFromMember(memberId, memberName, x, y) {
    if (usedMemberIds.has(memberId)) {
        alert('This member is already in the hierarchy');
        return;
    }

    const box = {
        id: memberId,
        x: Math.max(10, x - 100),
        y: Math.max(10, y - 60),
        width: 300,
        height: 120,
        name: memberName,
        text: 'Enter description here...'
    };

    boxes.push(box);
    usedMemberIds.add(memberId);

    const boxElement = document.createElement('div');
    boxElement.className = 'concept-box';
    boxElement.id = box.id;
    boxElement.style.left = box.x + 'px';
    boxElement.style.top = box.y + 'px';
    boxElement.style.width = box.width + 'px';
    boxElement.style.minHeight = box.height + 'px';

    boxElement.innerHTML = produceBoxHTML(box);
    workspace.appendChild(boxElement);



    // Add event listeners
    boxElement.addEventListener('mousedown', function(e) {
        if (e.target.classList.contains('field-input') || e.target.classList.contains('delete-btn')) {
            return;
        }

        if (currentTool === 'arrow') {
            e.preventDefault();
            e.stopPropagation();
            handleArrowClick(box.id);
        } else if (currentTool === 'deleteArrow') {
            e.preventDefault();
            e.stopPropagation();
            handleDeleteArrowClick(box.id);
        }
    });

    // Make draggable
    let isDragging = false;
    let startX, startY, startBoxX, startBoxY;

    const dragHandle = boxElement.querySelector('.drag-handle');
    dragHandle.addEventListener('mousedown', function(e) {
        e.preventDefault();
        e.stopPropagation();
        isDragging = true;
        startX = e.clientX / zoomLevel;
        startY = e.clientY / zoomLevel;
        startBoxX = box.x;
        startBoxY = box.y;
        boxElement.classList.add('dragging');

        document.addEventListener('mousemove', handleMouseMove);
        document.addEventListener('mouseup', handleMouseUp);
    });

    function handleMouseMove(e) {
        if (!isDragging) return;

        const newX = startBoxX + (e.clientX / zoomLevel - startX);
        const newY = startBoxY + (e.clientY / zoomLevel - startY);

        box.x = Math.max(0, newX);
        box.y = Math.max(0, newY);

        boxElement.style.left = box.x + 'px';
        boxElement.style.top = box.y + 'px';

        drawArrows();
    }

    function handleMouseUp(e) {
        isDragging = false;
        boxElement.classList.remove('dragging');
        document.removeEventListener('mousemove', handleMouseMove);
        document.removeEventListener('mouseup', handleMouseUp);
    }

    // Add input event listeners
    const nameInput = boxElement.querySelector('.name-input');
    const textInput = boxElement.querySelector('.text-input');

    if (nameInput) {
        nameInput.addEventListener('input', function() {
            box.name = this.value;
        });
    }

    if (textInput) {
        textInput.addEventListener('input', function() {
            box.text = this.value;
        });
    }

    adjustBoxSize(boxElement);
    filterMembers(); // Update sidebar to show this member as used
    drawArrows();
}

function produceBoxHTML(box) {
    return `
        <button class="delete-btn" onclick="deleteBox('${box.id}')" title="Delete">×</button>
        <div class="drag-handle" title="Drag to move">
            <div class="drag-icon"></div>
        </div>
        <div class="box-content">
            <div class="field-group">
                <label class="field-label">ID</label>
                <div class="id-display">${box.id}</div>
            </div>
            <div class="field-group">
                <label class="field-label">Name</label>
                <input type="text" class="field-input name-input" value="${box.name}">
            </div>
            <div class="field-group">
                <label class="field-label">Description</label>
                <textarea class="field-input text-input" rows="2">${box.text}</textarea>
            </div>
        </div>
    `;
}

function adjustBoxSize(boxElement) {
    const content = boxElement.querySelector('.box-content');
    if (content) {
        const rect = content.getBoundingClientRect();
        const minHeight = Math.max(120, rect.height + 50);
        boxElement.style.minHeight = minHeight + 'px';
    }
}

function handleArrowClick(boxId) {
    if (!connectingFrom) {
        connectingFrom = boxId;
        const boxElement = document.getElementById(boxId);
        if (boxElement) {
            boxElement.classList.add('connecting');
        }
        updateToolStatus();
    } else if (connectingFrom !== boxId) {
        createArrow(connectingFrom, boxId);
        const fromElement = document.getElementById(connectingFrom);
        if (fromElement) {
            fromElement.classList.remove('connecting');
        }
        connectingFrom = null;
        updateToolStatus();
    }
}

function handleDeleteArrowClick(boxId) {
    if (!deletingFrom) {
        deletingFrom = boxId;
        const boxElement = document.getElementById(boxId);
        if (boxElement) {
            boxElement.classList.add('deleting');
        }
    } else if (deletingFrom !== boxId) {
        deleteArrowBetweenBoxes(deletingFrom, boxId);
        const fromElement = document.getElementById(deletingFrom);
        if (fromElement) {
            fromElement.classList.remove('deleting');
        }
        deletingFrom = null;
    }
}

function deleteArrowBetweenBoxes(fromId, toId) {
    const index = arrows.findIndex(arrow =>
        (arrow.from === fromId && arrow.to === toId) ||
        (arrow.from === toId && arrow.to === fromId)
    );

    if (index !== -1) {
        arrows.splice(index, 1);
        drawArrows();
    }
}

function createArrow(fromId, toId) {
    // Check if arrow already exists
    const exists = arrows.some(arrow =>
        (arrow.from === fromId && arrow.to === toId) ||
        (arrow.from === toId && arrow.to === fromId)
    );

    if (!exists) {
        arrows.push({ from: fromId, to: toId });
        drawArrows();
    }
}

function deleteBox(boxId) {
    if (confirm('Are you sure you want to delete this concept?')) {
        // Remove from boxes array
        const boxIndex = boxes.findIndex(box => box.id === boxId);
        if (boxIndex !== -1) {
            boxes.splice(boxIndex, 1);
        }

        // Remove from used members
        usedMemberIds.delete(boxId);

        // Remove related arrows
        arrows = arrows.filter(arrow => arrow.from !== boxId && arrow.to !== boxId);

        // Remove DOM element
        const boxElement = document.getElementById(boxId);
        if (boxElement) {
            boxElement.remove();
        }

        drawArrows();
        filterMembers(); // Update sidebar
    }
}

function drawArrows() {
    if (!canvas || !ctx) return;

    // Clear canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Set high-quality rendering
    ctx.save();
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';

    // Draw all arrows
    arrows.forEach((arrow, index) => {
        const fromBox = boxes.find(box => box.id === arrow.from);
        const toBox = boxes.find(box => box.id === arrow.to);

        if (fromBox && toBox) {
            drawArrow(fromBox, toBox);
        }
    });

    ctx.restore();
}

function getActualBoxHeight(box) {
    const boxElement = document.getElementById(box.id);
    if (boxElement) {
        return boxElement.offsetHeight;
    }
    return box.height;
}

function getBoxEdgePoint(fromBox, toBox, isFrom) {
    const box = isFrom ? fromBox : toBox;
    const otherBox = isFrom ? toBox : fromBox;

    const boxHeight = getActualBoxHeight(box);

    // Box center
    const centerX = box.x + box.width / 2;
    const centerY = box.y + boxHeight / 2;

    // Other box center
    const otherCenterX = otherBox.x + otherBox.width / 2;
    const otherCenterY = otherBox.y + getActualBoxHeight(otherBox) / 2;

    // Direction vector
    const dx = otherCenterX - centerX;
    const dy = otherCenterY - centerY;

    // Determine which edge to use
    const absRatio = Math.abs(dx / dy);
    const boxRatio = box.width / boxHeight;

    let edgeX, edgeY;

    if (absRatio > boxRatio) {
        // Hit vertical edge
        if (dx > 0) {
            // Right edge
            edgeX = box.x + box.width;
            edgeY = centerY + (dy / dx) * (box.width / 2);
        } else {
            // Left edge
            edgeX = box.x;
            edgeY = centerY + (dy / dx) * (-box.width / 2);
        }
    } else {
        // Hit horizontal edge
        if (dy > 0) {
            // Bottom edge
            edgeX = centerX + (dx / dy) * (boxHeight / 2);
            edgeY = box.y + boxHeight;
        } else {
            // Top edge
            edgeX = centerX + (dx / dy) * (-boxHeight / 2);
            edgeY = box.y;
        }
    }

    return { x: edgeX, y: edgeY };
}

function drawArrow(fromBox, toBox) {
  const fromPoint = { x: fromBox.x + fromBox.width / 2, y: fromBox.y + getActualBoxHeight(fromBox) / 2 };
  const toPoint = { x: toBox.x + toBox.width / 2, y: toBox.y + getActualBoxHeight(toBox) / 2 };

    // Skip drawing if points are too close (overlapping boxes)
    const distance = Math.sqrt(
        Math.pow(toPoint.x - fromPoint.x, 2) + Math.pow(toPoint.y - fromPoint.y, 2)
    );
    if (distance < 10) return;

    // Save context state
    ctx.save();

    // Draw the line
    // Create gradient from red (source) to green (target)
    const gradient = ctx.createLinearGradient(fromPoint.x, fromPoint.y, toPoint.x, toPoint.y);
    gradient.addColorStop(1, '#e74c3c'); // Red at source
    gradient.addColorStop(0, '#27ae60'); // Green at target
    ctx.strokeStyle = gradient;
    ctx.lineWidth = 3;
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';

    ctx.beginPath();
    ctx.moveTo(fromPoint.x, fromPoint.y);
    ctx.lineTo(toPoint.x, toPoint.y);
    ctx.stroke();

    // Calculate arrow head
    const angle = Math.atan2(toPoint.y - fromPoint.y, toPoint.x - fromPoint.x);
    const arrowLength = 15;
    const arrowAngle = Math.PI / 6;

    // Calculate arrow head points
    const arrowHead1X = toPoint.x - arrowLength * Math.cos(angle - arrowAngle);
    const arrowHead1Y = toPoint.y - arrowLength * Math.sin(angle - arrowAngle);
    const arrowHead2X = toPoint.x - arrowLength * Math.cos(angle + arrowAngle);
    const arrowHead2Y = toPoint.y - arrowLength * Math.sin(angle + arrowAngle);

    // Draw arrow head
    ctx.fillStyle = '#667eea';
    ctx.strokeStyle = '#667eea';
    ctx.lineWidth = 2;

    ctx.beginPath();
    ctx.moveTo(toPoint.x, toPoint.y);
    ctx.lineTo(arrowHead1X, arrowHead1Y);
    ctx.lineTo(arrowHead2X, arrowHead2Y);
    ctx.closePath();
    ctx.fill();
    ctx.stroke();

    // Restore context state
    ctx.restore();
    ctx.save();
}


function clearAll() {
    if (confirm('Are you sure you want to clear all concepts and arrows?')) {
        boxes.forEach(boxData => {
            const boxElement = document.getElementById(boxData.id);
            if (boxElement) {
                boxElement.remove();
            }
        });

        boxes = [];
        arrows = [];
        usedMemberIds.clear();
        connectingFrom = null;
        deletingFrom = null;
        nextId = 1;

        drawArrows();
        filterMembers();
        setTool(null);
    }
}

function exportHierarchy() {
    if (boxes.length === 0) {
        alert('No concepts to export');
        return;
    }

    const exportData = {
        boxes: boxes,
        arrows: arrows,
        nextId: nextId,
        hierarchy_info: hierarchy_info
    };

    const dataStr = JSON.stringify(exportData, null, 2);
    const blob = new Blob([dataStr], { type: 'application/json' });
    const url = URL.createObjectURL(blob);

    const link = document.createElement('a');
    link.href = url;
    link.download = 'hierarchy.json';
    link.click();

    URL.revokeObjectURL(url);
}

function saveHierarchy() {
    if (boxes.length === 0) {
        alert('No concepts to save');
        return;
    }


    const hierarchyId = hierarchy_info.id

    // Get domain ID from hierarchy_info or use a default
    const domainId = hierarchy_info.domain;

    // Prepare visualization data
    const visualizationData = {
        boxes: boxes,
        arrows: arrows,
        nextId: nextId,
        hierarchy_info: hierarchy_info
    };

    // Prepare request data
    const requestData = {
        hierarchy_id: hierarchyId,
        name: hierarchyId,
        domain_id: hierarchy_info.domain,
        description: hierarchy_info.description,
        data: visualizationData
    };

    // Make API call
    fetch('/pybirdai/api/hierarchy/save/', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRFToken': '{{ csrf_token }}'
        },
        body: JSON.stringify(requestData)
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            alert(`Hierarchy "${hierarchyId}" saved successfully!`);
            // Optionally redirect to the new hierarchy
            if (confirm('Would you like to navigate to the saved hierarchy?')) {
                window.location.href = `/pybirdai/member_hierarchy_editor/${hierarchyId}/`;
            }
        } else {
            alert('Error saving hierarchy: ' + (data.error || 'Unknown error'));
        }
    })
    .catch(error => {
        alert('Error saving hierarchy: ' + error.message);
    });
}

function importHierarchy(event) {
    const file = event.target.files[0];
    if (!file) return;

    const reader = new FileReader();
    reader.onload = function(e) {
        try {
            const data = JSON.parse(e.target.result);

            // Clear existing data first
            boxes.forEach(boxData => {
                const boxElement = document.getElementById(boxData.id);
                if (boxElement) {
                    boxElement.remove();
                }
            });

            boxes = [];
            arrows = [];
            usedMemberIds.clear();

            // Import hierarchy info
            if (data.hierarchy_info) {
                hierarchy_info = data.hierarchy_info;
            }

            // Import boxes
            if (data.boxes) {
                data.boxes.forEach(boxData => {
                    createBoxFromImport(boxData);
                });
            }

            // Import arrows
            if (data.arrows) {
                arrows = data.arrows;
            }

            // Import nextId
            if (data.nextId) {
                nextId = data.nextId;
            }

            drawArrows();
            filterMembers();



        } catch (error) {
            alert('Error importing file: ' + error.message);
        }
    };
    reader.readAsText(file);
    event.target.value = ''; // Clear the input
}

function createBoxFromImport(boxData) {
    // Use saved position if available, otherwise auto-layout
    const autoPosition = boxData.x !== undefined ? { x: boxData.x, y: boxData.y } : getAutoLayoutPosition();

    const box = {
        id: boxData.id,
        x: autoPosition.x,
        y: autoPosition.y,
        width: boxData.width || 300,
        height: boxData.height || 120,
        name: boxData.name,
        text: boxData.text
    };

    boxes.push(box);
    usedMemberIds.add(box.id);

    const boxElement = document.createElement('div');
    boxElement.className = 'concept-box';
    boxElement.id = box.id;
    boxElement.style.left = box.x + 'px';
    boxElement.style.top = box.y + 'px';
    boxElement.style.width = box.width + 'px';
    boxElement.innerHTML = produceBoxHTML(box);
    workspace.appendChild(boxElement);

    // Add the same event listeners as createBoxFromMember
    setupBoxEventListeners(boxElement, box);
}

function setupBoxEventListeners(boxElement, box) {
    // Click handler for tools
    boxElement.addEventListener('mousedown', function(e) {
        if (e.target.classList.contains('field-input') || e.target.classList.contains('delete-btn')) {
            return;
        }

        if (currentTool === 'arrow') {
            e.preventDefault();
            e.stopPropagation();
            handleArrowClick(box.id);
        } else if (currentTool === 'deleteArrow') {
            e.preventDefault();
            e.stopPropagation();
            handleDeleteArrowClick(box.id);
        }
    });

    // Make draggable
    let isDragging = false;
    let startX, startY, startBoxX, startBoxY;

    const dragHandle = boxElement.querySelector('.drag-handle');
    if (dragHandle) {
        dragHandle.addEventListener('mousedown', function(e) {
            e.preventDefault();
            e.stopPropagation();
            isDragging = true;
            startX = e.clientX / zoomLevel;
            startY = e.clientY / zoomLevel;
            startBoxX = box.x;
            startBoxY = box.y;
            boxElement.classList.add('dragging');

            document.addEventListener('mousemove', handleMouseMove);
            document.addEventListener('mouseup', handleMouseUp);
        });
    }

    function handleMouseMove(e) {
        if (!isDragging) return;

        const newX = startBoxX + (e.clientX / zoomLevel - startX);
        const newY = startBoxY + (e.clientY / zoomLevel - startY);

        box.x = Math.max(0, newX);
        box.y = Math.max(0, newY);

        boxElement.style.left = box.x + 'px';
        boxElement.style.top = box.y + 'px';

        drawArrows();
    }

    function handleMouseUp(e) {
        isDragging = false;
        boxElement.classList.remove('dragging');
        document.removeEventListener('mousemove', handleMouseMove);
        document.removeEventListener('mouseup', handleMouseUp);
    }

    // Add input event listeners
    const nameInput = boxElement.querySelector('.name-input');
    const textInput = boxElement.querySelector('.text-input');

    if (nameInput) {
        nameInput.addEventListener('input', function() {
            box.name = this.value;
        });
    }

    if (textInput) {
        textInput.addEventListener('input', function() {
            box.text = this.value;
        });
    }
}



function loadHierarchy(hierarchyId) {
    if (!hierarchyId) {
        // Clear current hierarchy and reload without hierarchy ID
        window.location.href = window.location.pathname;
        return;
    }

    // Navigate to selected hierarchy
    const basePath = window.location.pathname.split('/').slice(0, -2).join('/');
    console.log(`Loading hierarchy with ID: ${hierarchyId}`);
    if (basePath.includes("/member_hierarchy_editor")) {
        window.location.href = `${basePath}/${hierarchyId}/`;
    } else {
      window.location.href = `${basePath}/member_hierarchy_editor/${hierarchyId}/`;
    }
}

// Event listeners
document.addEventListener('wheel', handleZoom, { passive: false });
window.addEventListener('resize', resizeCanvas);

// // Add ResizeObserver for better canvas management
// if (workspace && 'ResizeObserver' in window) {
//     const resizeObserver = new ResizeObserver(entries => {
//         for (let entry of entries) {
//             resizeCanvas();
//         }
//     });
//     resizeObserver.observe(workspace);
// }

// Add global mouse event handlers for canvas drag
document.addEventListener('mousemove', function(event) {
    if (isDraggingCanvas) {
        const rect = canvas.getBoundingClientRect();
        const x = event.clientX - rect.left;
        const y = event.clientY - rect.top;
        updateCanvasDrag(x, y);
        event.preventDefault();
    }
});

document.addEventListener('mouseup', function(event) {
    if (isDraggingCanvas) {
        endCanvasDrag();
        event.preventDefault();
    }
});



// Add canvas click handler for arrow deletion and drag navigation
if (canvas) {
    canvas.addEventListener('mousedown', function(event) {
        const rect = canvas.getBoundingClientRect();
        const x = event.clientX - rect.left;
        const y = event.clientY - rect.top;

        // Start canvas drag for navigation
        if (event.button === 0 && !currentTool) { // Left mouse button and no tool selected
            startCanvasDrag(x, y);
            event.preventDefault();
        }
    });

    canvas.addEventListener('mousemove', function(event) {
        if (isDraggingCanvas) {
            const rect = canvas.getBoundingClientRect();
            const x = event.clientX - rect.left;
            const y = event.clientY - rect.top;
            updateCanvasDrag(x, y);
            event.preventDefault();
        }
    });

    canvas.addEventListener('mouseup', function(event) {
        if (isDraggingCanvas) {
            endCanvasDrag();
            event.preventDefault();
        }
    });

    canvas.addEventListener('mouseleave', function(event) {
        if (isDraggingCanvas) {
            endCanvasDrag();
        }
    });

    canvas.addEventListener('click', function(event) {
        if (currentTool === 'deleteArrow') {
            // Handle clicking on arrows for deletion
            const rect = canvas.getBoundingClientRect();
            const x = (event.clientX - rect.left) / zoomLevel;
            const y = (event.clientY - rect.top) / zoomLevel;

            // Check if click is near any arrow
            for (let i = arrows.length - 1; i >= 0; i--) {
                const arrow = arrows[i];
                const fromBox = boxes.find(box => box.id === arrow.from);
                const toBox = boxes.find(box => box.id === arrow.to);

                if (fromBox && toBox) {
                    const fromPoint = getBoxEdgePoint(fromBox, toBox, true);
                    const toPoint = getBoxEdgePoint(toBox, fromBox, false);

                    // Check if click is near the arrow line
                    const distance = distanceToLineSegment(x, y, fromPoint.x, fromPoint.y, toPoint.x, toPoint.y);
                    if (distance < 10) { // 10px tolerance
                        arrows.splice(i, 1);
                        drawArrows();
                        break;
                    }
                }
            }
        }
    });
}

// Helper function to calculate distance from point to line segment
function distanceToLineSegment(px, py, x1, y1, x2, y2) {
    const dx = x2 - x1;
    const dy = y2 - y1;
    const length = Math.sqrt(dx * dx + dy * dy);

    if (length === 0) return Math.sqrt((px - x1) * (px - x1) + (py - y1) * (py - y1));

    const t = Math.max(0, Math.min(1, ((px - x1) * dx + (py - y1) * dy) / (length * length)));
    const projection = { x: x1 + t * dx, y: y1 + t * dy };

    return Math.sqrt((px - projection.x) * (px - projection.x) + (py - projection.y) * (py - projection.y));
}



// Single initialization handler for all page load behavior
document.addEventListener('DOMContentLoaded', function() {
  // Initialize
  resizeCanvas();

  {% if selected_hierarchy and hierarchy_data_json %}
      // Load initial hierarchy data
      try {
          const initialData = {{ hierarchy_data_json|safe }};
          hierarchy_info = initialData.hierarchy_info;

          if (initialData.boxes) {
              initialData.boxes.forEach(boxData => {
                  createBoxFromImport(boxData);
              });
          }

          if (initialData.arrows) {
              arrows = initialData.arrows;
          }

          if (initialData.nextId) {
              nextId = initialData.nextId;
          }



      } catch (error) {
          console.error('Error loading initial hierarchy data:', error);
      }
  {% endif %}
    setTimeout(() => {
        // Always populate sidebar and resize canvas
        populateSidebar();
        resizeCanvas();

        // Draw arrows if they exist
        if (arrows.length > 0) {
            drawArrows();
        }

        // Navigate to upper left open node if boxes exist

    }, 200);
});
</script>

{% endblock %}
